﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Xml;

using IServiceProvider = System.IServiceProvider;
using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;

namespace Mdv.wssAddins
{
    /// <summary>
    /// Summary description for MyControl.
    /// </summary>
    public partial class MyControl : UserControl
    {
        private string _schemaPath;
        private XmlDocument doc = null;
        private MyToolWindow pane;
        public MyControl(MyToolWindow myToolWindowPane)
        {
            InitializeComponent();
            pane = myToolWindowPane;
        }
        /// <summary> 
        /// Let this control process the mnemonics.
        /// </summary>
        protected override bool ProcessDialogChar(char charCode)
        {
              // If we're the top-level form or control, we need to do the mnemonic handling
              if (charCode != ' ' && ProcessMnemonic(charCode))
              {
                    return true;
              }
              return base.ProcessDialogChar(charCode);
        }
        private void MyControl_Click(object sender, EventArgs e)
        {
            tvSchema.Select();
        }
        public void LoadSchema(string schemaPath)
        {
            _schemaPath = schemaPath;
            tvSchema.Nodes.Clear();
            doc = new XmlDocument();
            doc.Load(schemaPath);
            XmlElement xdList = doc.DocumentElement;
            ProcessListNode(xdList);
            tvSchema.ExpandAll();
            pane.SelectList(new object[1] { null});//I have to make first a dummy selection otherwise the property page won't change
            pane.UpdateSelection();
        }
        protected void ProcessListNode(XmlElement listNode)
        {
            try
            {
                wss.wssList l = new wss.wssList();
                l.Load(listNode);
                l.ModelChanged += new EventHandler<Mdv.wssAddins.wss.ModelEventArgs>(ModelHasChanged);
                TreeNode tn = new TreeNode(l.ToString());
                tn.Tag = l;
                tvSchema.Nodes.Add(tn);
                ConstructTree(tn, l);
            }
            catch (Exception ex)
            {
                tvSchema.Nodes.Add(ex.Message);
            }
        }
        protected void ConstructTree(TreeNode rootNode, wss.Model rootObject)
        {
            foreach (wss.Model m in rootObject.Children)
            {
                TreeNode tn = new TreeNode(m.ToString());
                tn.Tag = m;
                rootNode.Nodes.Add(tn);
                m.ModelChanged += new EventHandler<Mdv.wssAddins.wss.ModelEventArgs>(ModelHasChanged);
                if (null != m.Children) ConstructTree(tn, m);
            }
        }
        private void tvSchema_MouseClick(object sender, MouseEventArgs e)
        {
            TreeView tv = (TreeView) sender;
	        Point p = new Point(e.X, e.Y);
            TreeNode node = tv.GetNodeAt(p);
            wss.Model selectedObject = node.Tag as wss.Model;
            if ((null != selectedObject) && (null != selectedObject.Actions) && (e.Button == MouseButtons.Right))
            {
                ContextMenu cm = new ContextMenu();
                foreach (wss.Action a in selectedObject.Actions)
                    cm.MenuItems.Add(new MenuItem(a.Name, a.ActionHandler));
                cm.Show(tv, p);
            }
        }
        private void tvSchema_AfterSelect(object sender, TreeViewEventArgs e)
        {
            object selectedObject = e.Node.Tag;
            if (null != selectedObject)
            {
                pane.SelectList(new object[1] { selectedObject });
                pane.UpdateSelection();
            }
        }
        private void ModelHasChanged(object sender, wss.ModelEventArgs e)
        {
            wss.Model m = (wss.Model)sender;
            if (null == sender) return;
            switch (e.ActionType)
            {
                case wss.ActionType.Added:
                    TreeNode parentNode = FindNodeForModel(tvSchema.Nodes[0], m);
                    wss.Model targetModel = e.AffectedNode;
                    TreeNode newNode = new TreeNode();
                    newNode.Text = targetModel.ToString();
                    newNode.Tag = e.AffectedNode;
                    targetModel.ModelChanged += new EventHandler<Mdv.wssAddins.wss.ModelEventArgs>(ModelHasChanged);
                    parentNode.Nodes.Add(newNode);
                    parentNode.Expand();
                    tvSchema.SelectedNode = newNode;
                    pane.SelectList(new object[1] { targetModel });
                    pane.UpdateSelection();
                    break;
                case wss.ActionType.Renamed:
                    TreeNode renamedNode = FindNodeForModel(tvSchema.Nodes[0], m);
                    renamedNode.Text = m.ToString();
                    break;
                case wss.ActionType.Deleted:
                    TreeNode deletedNode = FindNodeForModel(tvSchema.Nodes[0], m);
                    deletedNode.Remove();
                    break;
            }
        }
        private TreeNode FindNodeForModel(TreeNode start, wss.Model m)
        {
            TreeNode target = null;
            if (start.Tag == (Object)m) return start;
            foreach (TreeNode tn in start.Nodes)
            {
                target = FindNodeForModel(tn, m);
                if (null != target) return target;
            }
            return target;
        }
        private void Save_Click(object sender, EventArgs e)
        {
            wss.Model m = (wss.Model)tvSchema.Nodes[0].Tag;
            m.Save();
            if (null != doc) doc.Save(_schemaPath);
        }
        private void Reload_Click(object sender, EventArgs e)
        {
            LoadSchema(_schemaPath);
        }
    }
}